home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / dev / basic / ace24dist.lha / ace24.lha / utils / ab2ascii-1.3 / expand.c < prev    next >
C/C++ Source or Header  |  1996-09-11  |  9KB  |  428 lines

  1. /*
  2.  *  EXPAND.C
  3.  */
  4.  
  5. /*
  6.  * (c)Copyright 1994 by Tobias Ferber.
  7.  *
  8.  * This file is part of AmigaBASIC->ASCII.
  9.  *
  10.  * AmigaBASIC->ASCII is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License as
  12.  * published by the Free Software Foundation; either version 1 of the
  13.  * License, or (at your option) any later version.
  14.  *
  15.  * AmigaBASIC->ASCII is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with AmigaBASIC->ASCII; see the file COPYING.  If not, write to
  22.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  */
  24.  
  25. #include "abasic.h"
  26.  
  27. static unsigned char *codeptr;
  28.  
  29. /*
  30.    Print unknown token values and character codes and warn about them.
  31.    The value of n should be 1 (for one character) or 2 for a word of two.
  32. */
  33.  
  34. static void p_unknown(int n, ...)
  35. {
  36.   va_list argp;
  37.   va_start(argp, n);
  38.  
  39.   fprintf(ferr,"%s: ",whoami);
  40.  
  41.   if(infile)
  42.     fprintf(ferr,"%s: ",infile);
  43.  
  44.   fprintf(ferr,"%ld warning: Can't expand that token: ",current_line);
  45.  
  46.   if(n==1)
  47.   { vfprintf(ferr,"<0x%02x>",argp);
  48.     vfprintf(fout,"<0x%02x>",argp);
  49.   }
  50.   else /* n!=1 */
  51.   { vfprintf(ferr,"<0x%02x,0x%02x>",argp);
  52.     vfprintf(fout,"<0x%02x,0x%02x>",argp);
  53.   }
  54.  
  55.   fprintf(ferr,"\n");
  56.   fflush(ferr);
  57.   va_end(argp);
  58. }
  59.  
  60.  
  61. /*
  62.    These functions return the next byte, word, long, float or double from the
  63.    current code line (codeptr).  No memory border checking will be performed.
  64.    get_float() and get_double() are very, very hacky!
  65. */
  66.  
  67. static int get_byte( void )
  68. {
  69.   return ( (int)*codeptr++ ) & 0xFF;
  70. }
  71.  
  72.  
  73. static int get_word( void )
  74. {
  75.   return ( (*codeptr++ << 8) + *codeptr++ ) & 0xFFFF;
  76. }
  77.  
  78.  
  79. static long get_long( void )
  80. {
  81.   return ((long)get_word() << 16) + (long)get_word();
  82. }
  83.  
  84.  
  85. /*
  86.    Die 32 bit der Fließkommazahlen einfacher Genauigkeit von links nach rechts:
  87.  
  88.      1 bit   Vorzeichen  (0=pos, 1=neg)
  89.      7 bit   Exponent (2er-Potenz zur Multiplikation mit der Mantisse)
  90.     24 bit   Mantisse mit führendem 1 bit (normalisierte Darstellung: 1<= m <2)
  91.  
  92.     Beispiele:    1.0 = 0x3f800000           Die kleinste darstellbare Zahl ist
  93.                  -1.0 = 0xbf800000
  94.                   0.0 = 0x00xxxxxx                         -38
  95.                  10.0 = 0x41200000                 1.8 * 10
  96.                   0.1 = 0x3dcccccd
  97. */
  98.  
  99. static float get_float( void )
  100. {
  101.   float f;
  102.   *( (long *)&f ) = get_long();
  103.  
  104. #ifdef _DCC
  105.   f *= 4.0;
  106. #endif
  107.  
  108.   return f;
  109. }
  110.  
  111. /*
  112.    Die 64 bit der Fließkommazahlen doppelter Genauigkeit von links nach rechts:
  113.  
  114.      1 bit   Vorzeichen  (0=pos, 1=neg)
  115.     11 bit   Exponent (2er-Potenz zur Multiplikation mit der Mantisse)
  116.     52 bit   Mantisse mit führendem 1 bit (normalisierte Darstellung: 1<= m <2)
  117.  
  118.     Beispiele:    1.0 = 0x3ff0000000000000   Die kleinste darstellbare Zahl ist
  119.                  -1.0 = 0xbff0000000000000
  120.                   0.0 = 0x000xxxxxxxxxxxxx                  -308
  121.                  10.0 = 0x4024000000000000         2.23 * 10
  122.                   0.1 = 0x3fb9999999999999
  123. */
  124.  
  125. static double get_double( void )
  126. {
  127.   double d;
  128.   *( (long *)&d ) = get_long();
  129.   (void)get_long(); /* ? */
  130.   return d;
  131. }
  132.  
  133.  
  134. #define unget(n)  codeptr-=(n)
  135.  
  136.  
  137. static void expand_token( int t )
  138. {
  139.   switch( t )
  140.   {
  141.  
  142. /**/case 0x00:
  143.       fputc( '\n',fout );
  144.       break;
  145.  
  146. /**/case 0x01:  /* variable reference */
  147.       {
  148.         short id;
  149.         char *s;
  150.  
  151.         id= get_word();
  152.  
  153.         if( s = get_sym(id) )
  154.         {
  155.           fputs( s,fout );
  156.         }
  157.         else
  158.         {
  159.           fprintf(fout,"var%04x",id);
  160.           warn("%ld: warning: reference to undeclared variable id %d",
  161.             current_line,id);
  162.         }
  163.       }
  164.       break;
  165.  
  166. /**/case 0x02:  /* label definition */
  167.       {
  168.         short id;
  169.         char *s;
  170.  
  171.         id= get_word();
  172.  
  173.         if( s= get_sym(id) )
  174.         {
  175.           fputs( s,fout );
  176.         }
  177.         else
  178.         {
  179.           fprintf(fout,"label%04x",id);
  180.           warn("%ld: warning: label definition w/ undefined symbol id %d",
  181.             current_line,id);
  182.         }
  183.       }
  184.       break;
  185.  
  186. /**/case 0x03:  /* label reference */
  187.       if( get_byte() == 0)
  188.       {
  189.         short id;
  190.         char *s;
  191.  
  192.         id = get_word();
  193.  
  194.         if( s= get_sym(id) )
  195.         {
  196.           fputs( s,fout );
  197.         }
  198.         else
  199.         {
  200.           fprintf(fout,"label%04x",id);
  201.           warn("%ld: warning: reference to label w/ undefined symbol id %d",
  202.             current_line,id);
  203.         }
  204.       }
  205.       break;
  206.  
  207. /**/case 0x08:
  208.       get_byte(); /* conditional skip (introduced by <0xc4,0x44>) */
  209.       get_byte();
  210.       get_byte();
  211.       break;
  212.  
  213. /**/case 0x0e:    /* 0x00 + 2 byte line # reference */
  214.       get_byte();
  215.       fprintf( fout, "%d", get_word() );
  216.       break;
  217.  
  218. /**/case 0x0f:  /* 1 byte decimal integer */
  219.       fprintf( fout, "%d", get_byte() );
  220.       break;
  221.  
  222. /**/case 0x0c:  /* 2 byte hex integer */
  223.       fprintf( fout, "&H%x", get_word() );
  224.       break;
  225.  
  226. /**/case 0x1c:  /* 2 byte integer */
  227.       fprintf( fout, "%d", get_word() );
  228.       break;
  229.  
  230. /**/case 0x1d:  /* 4 byte float */
  231.       fprintf( fout, "%g", get_float() );
  232.       break;
  233.  
  234. /**/case 0x1e:  /* 4 byte decimal integer */
  235.       fprintf( fout, "%ld", get_long() );
  236.       break;
  237.  
  238. /**/case 0x1f:  /* 8 byte double */
  239.       fprintf( fout, "%g", get_double() );
  240.       break;
  241.  
  242. /**/case '\"':
  243.       {
  244.         int c;
  245.  
  246.         fputc( t,fout );
  247.         for(;;)
  248.         {
  249.           c= get_byte();
  250.  
  251.           if(c)
  252.           {
  253.             fputc( c,fout );
  254.  
  255.             if( c == '\"' )
  256.             {
  257.               c= get_byte();
  258.               if( c == '\"' )
  259.               {
  260.                 fputc( c,fout );
  261.               }
  262.               else
  263.               {
  264.                 unget(1);
  265.                 break;
  266.               }
  267.             }
  268.           }
  269.           else /* c == '\0' */
  270.           {
  271.             unget(1);
  272.             break;
  273.           }
  274.         }
  275.       }
  276.       break;
  277.  
  278. /**/case 0x3a:
  279.       t= get_word();
  280.       if(t != 0xafe8) /* tick'ed REMark */
  281.         fputc( 0x3a, fout );
  282.       unget(2);
  283.       break;
  284.  
  285. /**/case 0xaf: /* REM */
  286.       {
  287.         int c= get_byte();
  288.  
  289.         if( c != 0xe8 )
  290.         {
  291.           fputs( tok_tab[t-tok_min], fout );
  292.           unget(1);
  293.         }
  294.         else fputs( tok_tab[c-tok_min], fout );
  295.  
  296.         while( c= get_byte() )
  297.           fputc( c,fout );
  298.  
  299.         fputc( '\n',fout );
  300.       }
  301.       break;
  302.  
  303. /**/case 0xbe: /* WHILE */
  304.       fputs( tok_tab[t-tok_min], fout );
  305.       get_byte();
  306.       break;
  307.  
  308. /**/case 0xf8:
  309.       t= get_byte();
  310.       if( f8_min <= t && t <= f8_max )
  311.       {
  312.         if(f8_tab[t-f8_min])
  313.           fputs( f8_tab[t-f8_min], fout );
  314.         else
  315.           p_unknown(2, 0xf8,t);
  316.       }
  317.       else p_unknown(2, 0xf8,t);
  318.       break;
  319.  
  320. /**/case 0xf9:
  321.       t= get_byte();
  322.       if( f9_min <= t && t <= f9_max )
  323.       {
  324.         if(f9_tab[t-f9_min])
  325.           fputs( f9_tab[t-f9_min], fout );
  326.         else
  327.           p_unknown(2, 0xf9,t);
  328.       }
  329.       else p_unknown(2, 0xf9,t);
  330.       break;
  331.  
  332. /**/case 0xfa:
  333.       t= get_byte();
  334.       if( fa_min <= t && t <= fa_max )
  335.       {
  336.         if(fa_tab[t-fa_min])
  337.           fputs( fa_tab[t-fa_min], fout );
  338.         else
  339.           p_unknown(2, 0xfa,t);
  340.       }             
  341.       else p_unknown(2, 0xfa,t);
  342.       break;
  343.  
  344. /**/case 0xfb:
  345.       t= get_byte();
  346.       if( fb_min <= t && t <= fb_max )
  347.       {
  348.         if(fb_tab[t-fb_min])
  349.           fputs( fb_tab[t-fb_min], fout );
  350.         else
  351.           p_unknown(2, 0xfb,t);
  352.       }
  353.       else p_unknown(2, 0xfb,t);
  354.       break;
  355.  
  356.  
  357. /**/default:
  358.       if( 0x11 <= t && t <= 0x1a)
  359.       {
  360.         fputc( t - 0x11 + '0', fout );  /* digits '0'..'9' */
  361.       }
  362.  
  363.       else if( tok_min <= t && t <= tok_max)
  364.       {
  365.         if(tok_tab[t-tok_min])
  366.           fputs( tok_tab[t-tok_min], fout );
  367.         else
  368.           p_unknown(1,t);
  369.       }
  370.  
  371.       else
  372.       {
  373.         if( isprint(t) )
  374.           fputc( t,fout );
  375.         else
  376.           p_unknown(1,t);
  377.       }
  378.  
  379.       break;
  380.   }
  381. }
  382.  
  383.  
  384. void expand_code( void )
  385. {
  386.   for(current_line=1; code_buffer; current_line++)
  387.   {
  388.     codeline_t *cl= code_buffer;
  389.     char *s= codeptr= cl->s;
  390.  
  391.     int i= get_byte(); /* indentation */
  392.     while(i--) fputc( ' ',fout );
  393.  
  394.     if(cl->flags)
  395.     {
  396.       switch(cl->flags)
  397.       {
  398.         case 0x80: /* line # definition */
  399.           fprintf( fout,"%d ",get_word() ); /* decimal number plus 1 space character */
  400.           break;
  401.  
  402.         default:
  403.           warn("%d: warning: unknown code line prefix 0x%02x",
  404.             current_line, cl->flags);
  405.           break;
  406.       }
  407.     }
  408.  
  409.     do {
  410.  
  411.       expand_token( get_byte() );
  412.  
  413.     } while( (long)codeptr - (long)s < cl->len );
  414.  
  415.     if( (long)codeptr - (long)s != cl->len )
  416.       warn("%d: warning: expanded %ld of %d code bytes",
  417.         current_line, (long)codeptr - (long)s, cl->len);
  418.  
  419.     code_buffer= code_buffer->next;
  420.  
  421.     free(cl->s);
  422.     free(cl);
  423.   }
  424.  
  425.   if(current_line-1 != numlines)
  426.     warn("warning: expanded %ld of %ld code lines", current_line-1, numlines);
  427. }
  428.